console.log('1');

setTimeout(function () {
    console.log('2');

    new Promise(function (resolve) {
        console.log('4');
        resolve();
    }).then(function () {
        console.log('5')
    })

    process.nextTick(function () { // process.nextTick 会在此次事件循环中抢先注册，因此在微任务promise.then 的前面输出
        console.log('3');
    })
})

new Promise(function (resolve) {
    console.log('7');
    resolve();
}).then(function () {
    console.log('8')
})

process.nextTick(function () {
    console.log('6');
})

setTimeout(function () {
    console.log('9');
    process.nextTick(function () {
        console.log('10');
    })
    new Promise(function (resolve) {
        console.log('11');
        resolve();
    }).then(function () {
        console.log('12')
    })
})



// 宏任务：setTimeout  setInterval  setImmediate  requestAnimationFrame     宏任务通过 Web APIs 压入 Callback queue
// 微任务：process.nextTick(Node端)   MutationObserver(浏览器端)  Promise.then catch finally  微任务被压入 micro task queue
// 微任务是JS级别的，宏任务是宿主级别的，是包含关系，不是先后关系。
// 微任务是JS级别的，宏任务是宿主级别的，是包含关系，不是先后关系。

// 事件循环， 每次事件循环执行一次宏任务（宏任务里面有同步代码，和微任务  会继续按照先执行完同步代码再执行微任务）， 先执行完同步代码， 后执行完微任务， 此时该宏任务结束，开始下次事件循环

// process.nextTick方法可以在当前"执行栈"的尾部----下一次Event Loop（主线程读取"任务队列"）之前----触发回调函数
// process.nextTick是微任务
//  1 7  6  8  2  4   3  5   9  11   10    12
//  本题经理了三次事件循环
//  第一次循环 直接执行 1 7  宏任务Event Queue  setTimeout1   setTimeout2 	微任务Event Queue  process1  then1
//  执行栈为空， 执行微任务  process1  then1  6 8
//  第二次循环   先执行宏任务setTimeout1    此时注册表： 宏任务Event Queue setTimeout2  	微任务Event Queue  process2  then2
//  先打印 2  4 后 执行微任务   process2  then2   3  5  此时执行栈为空
//  第三次循环  执行宏任务  setTimeout2  同理 ....
// 宏任务：setTimeout setInterval setImmediate requestAnimationFrame	MessageChannel
// 微任务：process.nextTick 	MutationObserver 	Promise.then


// 注意：1.Call Stack 调用栈空闲 -> 2.尝试 DOM 渲染 -> 触发 Event loop。

// 每次 Call Stack 清空（即每次轮询结束），即同步任务执行完。
// 都是 DOM 重新渲染的机会，DOM 结构有改变则重新渲染。
// 然后再去触发下一次 Event loop。

